﻿using System;
using BasicFramework.Helper;
using SlimDX.Direct3D9;
using System.Drawing;
using System.Diagnostics;

namespace BasicFramework.Devices.DirectX9
{
    public class DX9DeviceContext : DeviceContextBase
    {
        #region Fields

        private Device device;
        private Direct3D direct3D;
        private DX9DeviceSettings settings;
        private PresentParameters presentParameters;

        #endregion


        #region Properties

        public DX9DeviceSettings Settings
        {
            get { return settings; }
        }

        public PresentParameters PresentParameters
        {
            get { return presentParameters; }
            set { this.presentParameters = value; }
        }

        public Direct3D Direct3D
        {
            get { return direct3D; }
        }

        public Device Device
        {
            get { return this.device; }
        }

        #endregion


        #region Constructors

        public DX9DeviceContext()
        {
            // Set DirectX Version
            this.DXVersion = 9;

            // Create PresentParameters
            this.presentParameters = new PresentParameters();

            // Set default Present Parameters Values
            this.PresentParameters.BackBufferFormat = Format.A8R8G8B8;
            this.PresentParameters.BackBufferCount = 1;
            this.PresentParameters.BackBufferWidth = 800;
            this.PresentParameters.BackBufferHeight = 600;
            this.PresentParameters.Multisample = MultisampleType.None;
            this.PresentParameters.SwapEffect = SwapEffect.Discard;
            this.PresentParameters.EnableAutoDepthStencil = true;
            this.PresentParameters.AutoDepthStencilFormat = Format.D16;
            this.PresentParameters.PresentFlags = PresentFlags.DiscardDepthStencil;
            this.PresentParameters.PresentationInterval = PresentInterval.Default;
            this.PresentParameters.Windowed = true;
        }

        #endregion


        #region Events

        #endregion


        #region Private methods

        internal override void InitializeDevice(IntPtr handle, IDeviceSettings deviceSettings)
        {
            if (handle == IntPtr.Zero)
            {
                Logger.Error("Value must be a valid window handle.");
                throw new ArgumentException("Value must be a valid window handle.", "handle");
            }
            if (deviceSettings == null)
            {
                Logger.Error("DeviceSettings are not assigned");
                throw new ArgumentNullException("deviceSettings");
            }

            if (deviceSettings.DXVersion == this.DXVersion)
            {
                // Set Settings object  
                this.settings = deviceSettings as DX9DeviceSettings;
            }
            else
            {
                Logger.Error("Wrong DirectX Version of settings object");
                Debug.Fail("Wrong DirectX Version of settings object");
            }

            // Set Window handle

            this.PresentParameters.DeviceWindowHandle = handle;

            try
            {
                Logger.Info("Initializing Device");
                this.direct3D = new Direct3D();
                this.device = new Device(this.Direct3D, this.Settings.AdapterNumber, DeviceType.Hardware, handle, this.Settings.CreationFlags, this.PresentParameters);
                Logger.Info("Initializing Device successful");
            }
            catch (Exception ex)
            {
                Logger.Exception(ex);
            }
        }


        internal override void OnResize(Size size)
        {
            this.PresentParameters.BackBufferWidth = size.Width;
            this.PresentParameters.BackBufferHeight = size.Height;

            if (this.device != null)
            {
                this.device.Reset(this.PresentParameters);
            }
        }

        internal override void ResetDevice()
        {
            if (this.device != null)
            {
                this.device.Reset(this.PresentParameters);
            }
        }


        internal override void Dispose(bool disposing)
        {
            if (this.device != null)
            {
                this.device.Dispose();
            }
            if (this.Direct3D != null)
            {
                this.Direct3D.Dispose();
            }
        }


        public override void DrawIndexedPrimitives(PrimitiveType primitiveType, int baseVertexIndex, int minimumVertexIndex, int verticeCount, int startIndex, int primitiveCount)
        {
            if (this.device.Indices != null)
            {
                this.device.DrawIndexedPrimitives(primitiveType, baseVertexIndex, minimumVertexIndex, verticeCount,
                                                  startIndex, primitiveCount);
            }
      


        }



        public override void SetTexture(string texturePath)
        {
            //this.device.VertexFormat = VertexFormat.Texture0;

            BaseTexture texture = Texture.FromFile(this.device, texturePath);

            device.SetTexture(0, texture);
        }

        #endregion

    }
}
